import 'dart:typed_data';
import 'dart:async';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
import 'xapp_utils.dart';

class WidgetToImageUtils {
  static WidgetToImageUtils? _instance;

  static WidgetToImageUtils getInstance() {
    if (_instance == null) {
      _instance = new WidgetToImageUtils();
    }
    return _instance!;
  }

  void createWidget(
      {@required Widget? widget,
      @required Function(Future<Uint8List> Function() create)? onBuild}) async {
    var overlayState = Overlay.of(XAppUtils.getInstance().getContext());
    OverlayEntry overlayEntry = new OverlayEntry(builder: (context) {
      return RepaintBoundary(
        child: _BindWidget(
          child: widget!,
          onBuild: (boundary) async {
            var create = () async {
              ui.Image image = await boundary.toImage(pixelRatio: 3.0);
              ByteData? byteData =
                  await image.toByteData(format: ui.ImageByteFormat.rawRgba);
              Uint8List _uInt8List = byteData!.buffer.asUint8List();
              return _uInt8List;
            };
            onBuild!(create);
          },
        ),
      );
    });
    overlayState?.insert(overlayEntry);
  }
}

class _BindWidget extends StatefulWidget {
  final Widget? child;
  final Function(RenderRepaintBoundary boundary)? onBuild;
  _BindWidget({this.child, this.onBuild});

  @override
  State<StatefulWidget> createState() => _BindWidgetState();
}

class _BindWidgetState extends State<_BindWidget> {
  @override
  void initState() {
    super.initState();
    WidgetsBinding widgetsBinding = WidgetsBinding.instance!;
    widgetsBinding.addPostFrameCallback((callback) {
      RenderRepaintBoundary? boundary =
          context.findAncestorRenderObjectOfType<RenderRepaintBoundary>();
      widget.onBuild!(boundary!);
    });
  }

  @override
  Widget build(BuildContext context) {
    return widget.child!;
  }
}
